/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package assisisw.smartcal.entitysubsystem;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;

/**
 *
 * @author Francesco
 */
@Entity
@Table ( name = "event" , catalog = "smartcal" )
public class Event implements Serializable 
{
 
    public static final String PUBLIC_VISIBILITY = "PUBLIC" ;
    
    public static final String PRIVATE_VISIBILITY = "PRIVATE" ;
    
    // Static Methods
    
    public static void copySimpleData ( Event src , Event dest ) 
    {
        dest.setEndDate ( src.getEndDate () ) ;
        dest.setIniDate ( src.getIniDate () ) ;
        dest.setName ( src.getName () ) ;
        dest.setOutdoor ( src.isOutdoor () ) ;
        dest.setPlace ( src.getPlace () ) ;
        dest.setVisibility ( src.getVisibility () ) ;
        dest.setWeatherInfo ( src.getWeatherInfo () ) ;
    }
    
    // Instance Fields
    
    /***/
    @Column ( name = "id" , unique = true , updatable = false )
    @GeneratedValue ( strategy = GenerationType.TABLE , generator = "eventgen" )
    @Id
    @TableGenerator ( 
        allocationSize = 5 , 
        name = "eventgen" , 
        pkColumnName = "seqname" , 
        pkColumnValue = "eventseq" , 
        table = "smartcal.sequences" , 
        valueColumnName = "seqnumber" )
    private Integer id;

    /***/
    @Column ( name = "name" , unique = false , updatable = true )
    @NotNull 
    private String name ;
    
    /***/
    @NotNull
    @Column ( name = "initialdate" )
    @Temporal ( TemporalType.TIMESTAMP )
    private Date iniDate ;
    
    /***/
    @NotNull
    @Column ( name = "enddate" )
    @Temporal ( TemporalType.TIMESTAMP )
    private Date endDate ;
    
    /***/
    @Column ( name = "isoutdoor" , unique = false , updatable = true )
    @NotNull
    private boolean outdoor ;
    
    /***/
    @Column ( name = "place" , unique = false , updatable = true )
    @NotNull
    private String place ;
    
    /***/
    @Column ( name = "weatherinfo" , unique = false , updatable = true )
    @NotNull
    private String weatherInfo ;
    
    /***/
    @Column ( name = "visibility" , unique = false , updatable = true )
    @NotNull
    private String visibility ;
    
    /***/
    @NotNull
    @JoinColumn ( name = "calendarid" )
    @ManyToOne ( fetch = FetchType.EAGER , 
                 cascade = { CascadeType.DETACH , CascadeType.MERGE , CascadeType.REFRESH } )
    private Calendar owningCalendar ;
    
    /***/
    @NotNull
    @JoinTable ( name = "smartcal.invitation" , 
                 joinColumns = { @JoinColumn ( name = "eventid" , referencedColumnName = "id" ) } , 
                 inverseJoinColumns = { @JoinColumn ( name = "usermail" , referencedColumnName = "mail" ) } )
    @ManyToMany ( fetch = FetchType.EAGER , 
                  cascade = { CascadeType.DETACH , CascadeType.REFRESH })
    private List < User > invitedUsers ;
    
    /***/
    @NotNull
    @OneToMany ( mappedBy = "generatingEvent" , 
                 fetch = FetchType.EAGER , 
                 cascade = { CascadeType.ALL } )
    private List < Notification > notifications ;
    
    // Instance Methods
    
    /***/
    public Event ()
    {
        invitedUsers = new ArrayList <> ( 0 ) ;
        notifications = new LinkedList <> () ;
        outdoor = false ;
        visibility = PUBLIC_VISIBILITY ;
    }
    
    /**
     * @param name
     * @param iniDate
     * @param endDate
     * @param isOutdoor  
     * @param visibility 
     * @param owningCalendar 
     */
    public Event ( String name , Date iniDate , Date endDate , boolean isOutdoor , String visibility , Calendar owningCalendar ) 
    {
        this () ;
        if ( name != null && iniDate != null && endDate != null && visibility != null && owningCalendar != null && ( endDate.equals ( iniDate ) || iniDate.before ( endDate ) ) )
        {
            this.name = name ;
            this.iniDate = iniDate ;
            this.endDate = endDate ;
            this.outdoor = isOutdoor ;
            this.visibility = visibility ;
            this.owningCalendar = owningCalendar ;
        }
        else
            throw new IllegalArgumentException () ;
    }

    /**
     * AS THE SUPER'S ONE.
     */
    @Override
    public int hashCode () 
    {
        int hash ;
        hash = id.hashCode () ;
        return hash ;
    }

    /**
     * AS THE SUPER'S ONE.
     */
    @Override
    public boolean equals ( Object object )
    {
        Event other ;
        boolean res ;
        if ( object instanceof Event )
        {
            other = ( Event ) object ;
            res = id == other.getId () ;
        }
        else
            res = false ;
        return res ;
    }

    /**
     * AS THE SUPER'S ONE.
     */
    @Override
    public String toString () 
    {
        return "Event :\nId : " + id ;
    }
    
    public void setId ( int id ) 
    {
        this.id = id ;
    }
    
    /**
     * @return
     */
    public Integer getId () 
    {
        return id;
    }
    
    /**
     * @param newName
     * @throws IllegalArgumentException
     */
    public void setName ( String newName ) 
    {
        if ( newName != null && ! newName.isEmpty () )
            this.name = newName ;
        else
            throw new IllegalArgumentException () ;
    }
    
    /***/
    public String getName () 
    {
        return name ;
    }
    
    /**
     * @param iniDate
     * @throws IllegalArgumentException
     */
    public void setIniDate ( Date iniDate ) 
    {
        if ( iniDate != null )
            this.iniDate = iniDate ;
        else
            throw new IllegalArgumentException () ;
    }
    
    /***/
    public String getPlace () 
    {
        return place ;
    }
    
    /**
     * @param place
     */
    public void setPlace ( String place ) 
    {
        this.place = place ;
    }
    
    /***/
    public Date getIniDate () 
    {
        return iniDate ;
    }
    
    /**
     * @param endDate 
     * @throws IllegalArgumentException
     */
    public void setEndDate ( Date endDate ) 
    {
        if ( endDate != null )
            this.endDate = endDate ;
        else
            throw new IllegalArgumentException () ;
    }
    
    /***/
    public Date getEndDate () 
    {
        return endDate ;
    }
    
    /**
     * @param outdoor 
     */
    public void setOutdoor ( boolean outdoor ) 
    {
        this.outdoor = outdoor ;
    }
    
    /**
     * @return
     */
    public boolean isOutdoor () 
    {
        return outdoor ;
    }
    
    /**
     * @param weatherInfo 
     */
    public void setWeatherInfo ( String weatherInfo ) 
    {
        this.weatherInfo = weatherInfo ;
    }
    
    /**
     * @return
     */
    public String getWeatherInfo () 
    {
        return weatherInfo ;
    }
    
    public void setVisibility ( String visibility ) 
    {
        if ( visibility != null )
            this.visibility = visibility ;
        else
            throw new IllegalArgumentException () ;
    }
    
    /***/
    public String getVisibility () 
    {
        return visibility ;
    }
    
    /***/
    public void setOwningCalendar ( Calendar owningCalendar ) 
    {
        this.owningCalendar = owningCalendar ;
    }
    
    /***/
    public Calendar getOwningCalendar () 
    {
        return owningCalendar ;
    }
    
    public void setInvitedUsers ( List < User > invitedUsers ) 
    {
        this.invitedUsers = invitedUsers ;
    }
    
    /**
     * @return
     */
    public List < User > getInvitedUsers () 
    {
        return invitedUsers ;
    }
    
    public void setNotifications ( List < Notification > notifications ) 
    {
        this.notifications = notifications ;
    }
    
    /**
     * @return
     */
    public List < Notification > getNotifications () 
    {
        return notifications ;
    }
    
}
